package com.xquant.trade.trade.service.impl;

import com.xquant.trade.trade.entity.BalanceChange;
import com.xquant.trade.trade.mapper.SettleMapper;
import com.xquant.trade.trade.service.SettleService;
import com.xquant.trade.utils.CommResponse;
import com.xquant.trade.utils.DateUtils;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.stereotype.Component;
import org.springframework.transaction.TransactionDefinition;

import java.text.MessageFormat;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 日终跑批 清算
 */
@Component
public class SettleServiceImpl extends TradeServiceAbstract implements SettleService {
    @Autowired
    private DayEndServiceFactory dayEndServiceFactory;
    @Autowired
    private SettleMapper settleMapper;
    @Autowired
    DataSourceTransactionManager dataSourceTransactionManager;
    @Autowired
    TransactionDefinition transactionDefinition;

    @Autowired
    private TradeServiceFactory factory;
    private org.slf4j.Logger log = LoggerFactory.getLogger(SettleServiceImpl.class);
    private boolean isRunning = false;
    private StringBuilder sb = new StringBuilder();
    private String tmpInfo = "";
    private String blcDate = null;

    private void appendSettleInfo(String info) {
        sb.append(MessageFormat.format("{0} {1}\r\n", DateUtils.getCurr_YYYY_MM_DD_HH_MM_SS(), info));
        log.info(info);
    }

    @Override
    public Map getSettleInfo() {
        Map ret = new HashMap();
        ret.put("isRunning", isRunning);
        ret.put("settleInfo", sb.append(tmpInfo).toString());
        return ret;
    }

    /**
     * 获取业务日期
     */
    @Override
    public String getBlcDate() {
        blcDate = settleMapper.getBlcDate();
        if (blcDate == null) {
            return DateUtils.getCurrentDate();
        }

        return blcDate;
    }

    /**
     * 清算前处理
     */
    public CommResponse beforeSettle(BalanceChange change) {
        CommResponse response = new CommResponse(true);
        appendSettleInfo("开始清算前处理");
        appendSettleInfo("开始回滚当前持仓数据");

        //response = this.tradeRollbackBalance(change);
        if (!response.isSuccess()) {
            return response;
        }
        //response = this.tradePoRollbackBalance(change);
        if (!response.isSuccess()) {
            return response;
        }
        //settleMapper.rollbackBalanceP(change);
        //settleMapper.rollbackBalance(change);

        appendSettleInfo("完成回滚当前持仓数据");
        appendSettleInfo("完成清算前处理");
        return response;
    }

    /**
     * 清算 一天一天清算
     */
    public CommResponse settleOneDay(BalanceChange change) {
        CommResponse response = new CommResponse(true);
        String date = change.getChangeDate();

        appendSettleInfo(MessageFormat.format("开始清算【{0}】", date));
        // 处理分红、送股
        //appendSettleInfo(MessageFormat.format("开始处理【{0}】的【分红送股】", date));
        //response = this.tradePoProcessBonus(change);
        if (!response.isSuccess()) {
            return response;
        }
        //response = this.tradeProcessBonus(change);
        if (!response.isSuccess()) {
            return response;
        }
        //settleMapper.processBonusP(change);
        //settleMapper.processBonus(change);
        //appendSettleInfo(MessageFormat.format("完成处理【{0}】的【分红送股】", date));
        // 处理日间交易
        //appendSettleInfo(MessageFormat.format("开始处理【{0}】的【日间交易】", date));
        //response = this.tradePoProcessTrade(change);
        if (!response.isSuccess()) {
            return response;
        }
        //response = this.tradeProcessTrade(change);
        if (!response.isSuccess()) {
            return response;
        }
        //settleMapper.processTradeP(change);
        //settleMapper.processTrade(change);
        //appendSettleInfo(MessageFormat.format("完成处理【{0}】的【日间交易】", date));
        // 处理日终计提
        //appendSettleInfo(MessageFormat.format("开始处理【{0}】的【日终计提】", date));
        //response = processDayEnd(change);
        if (!response.isSuccess()) {
            return response;
        }
        //appendSettleInfo(MessageFormat.format("完成处理【{0}】的【日终计提】", date));
        // 当前持仓备份到历史表
        //appendSettleInfo(MessageFormat.format("开始处理【{0}】的【持仓备份】", date));
        //response = this.tradePoBackupBalance(change);
        if (!response.isSuccess()) {
            return response;
        }
        //response = this.tradeBackupBalance(change);
        if (!response.isSuccess()) {
            return response;
        }
        //settleMapper.backupBalanceP(change);
        //settleMapper.backupBalance(change);
        appendSettleInfo(MessageFormat.format("完成处理【{0}】的【持仓备份】", date));
        appendSettleInfo(MessageFormat.format("完成清算【{0}】", date));
        return response;
    }

    /**
     * 清算后处理
     */
    public CommResponse afterSettle(BalanceChange change) {
        CommResponse response = new CommResponse(true);
        /*// 处理分红、送股
        response = this.tradePoProcessBonus(change);
        if (!response.isSuccess()) {
            return response;
        }
        response = this.tradeProcessBonus(change);
        if (!response.isSuccess()) {
            return response;
        }
        //settleMapper.processBonusP(change);
        //settleMapper.processBonus(change);
        // 处理日间交易
        response = this.tradePoProcessTrade(change);
        if (!response.isSuccess()) {
            return response;
        }
        response = this.tradeProcessTrade(change);
        if (!response.isSuccess()) {
            return response;
        }*/

        //settleMapper.processTradeP(change);
        //settleMapper.processTrade(change);
        return response;
    }

    @Override
    public CommResponse settleDays(String begDate, String endDate) throws Exception {
        CommResponse commResponse = new CommResponse(true);

        if (isRunning) {
            appendSettleInfo("系统正在清算");
            throw new Exception("系统正在清算");
        }
        try {
            isRunning = true;
            sb = new StringBuilder();
            BalanceChange change = new BalanceChange();
            change.setChangeDate(begDate);
            // 清算前处理
            commResponse = beforeSettle(change);
            if (!commResponse.isSuccess()) {
                isRunning = false;
                appendSettleInfo(commResponse.getMsg() + "");
                //手动回滚事务！
                return commResponse;
            }
            // 开始一天天清算
            while (change.getChangeDate().compareTo(endDate) <= 0) {
                //手动开启事务！
                //检查待审批的交易
                //commResponse = this.checkApproval(change);
                if (!commResponse.isSuccess()) {
                    isRunning = false;
                    appendSettleInfo(commResponse.getMsg() + "");
                    //手动回滚事务！
                    break;
                }
                //清算 一天一天清算
                commResponse = settleOneDay(change);
                if (!commResponse.isSuccess()) {
                    isRunning = false;
                    appendSettleInfo(commResponse.getMsg() + "");
                    break;
                }
                //日期加 +1
                change.setChangeDate(DateUtils.addDate(change.getChangeDate(), 1));
                blcDate = change.getChangeDate();
            }
            //日终跑批 在某个日期失败 返回并回滚当前日期
            if (!commResponse.isSuccess()) {
                isRunning = false;
                return commResponse;
            }
            // 清算后处理
            commResponse = afterSettle(change);
            if (!commResponse.isSuccess()) {
                isRunning = false;
                appendSettleInfo(commResponse.getMsg() + "");
                return commResponse;
            }
        } catch (Exception ex) {
            log.error(ex.toString());
            ex.printStackTrace();
            appendSettleInfo(ex.getLocalizedMessage());
            commResponse.setSuccess(false);
            commResponse.setMsg("清算失败" + ex.getMessage());
            throw ex;
        } finally {
            isRunning = false;
        }
        return commResponse;
    }

    /**
     * 检查未审批的交易
     */
    public CommResponse checkApproval(BalanceChange change) {

        return CommResponse.success();
    }

    /**
     * 处理日终 例如：计息
     */
    public CommResponse processDayEnd(BalanceChange change) {
        CommResponse response = new CommResponse(true);

        return response;
    }

    @Override
    public String[] getTradeTypes() {
        return new String[0];
    }

    @Override
    public List getTradeColumnCfglist() {
        return null;
    }
}
